package com.ddh.codeduck.infra.websocket.handler;

import cn.hutool.json.JSONUtil;
import com.ddh.codeduck.infra.websocket.model.WebSocketMessage;
import com.ddhcodeduck.common.enums.MessageType;
import com.ddhcodeduck.common.exception.BusinessException;
import com.ddhcodeduck.common.exception.ErrorCode;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import org.springframework.web.socket.CloseStatus;
import org.springframework.web.socket.TextMessage;
import org.springframework.web.socket.WebSocketSession;
import org.springframework.web.socket.handler.TextWebSocketHandler;

import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

@Component
@Slf4j
public class UserWebSocketHandler extends TextWebSocketHandler {

    // 存储所有连接的用户 session
    private static final Map<String, WebSocketSession> sessions = new ConcurrentHashMap<>();

    /**
     * 当 WebSocket 连接建立时触发。
     * 主要作用：
     * - 从 session 的 attributes 中获取拦截器设置的用户 ID（userId）
     * - 如果用户未登录（userId 为空），则拒绝连接并关闭 session
     * - 否则将用户与 session 关联并存入 sessions 映射表中
     *
     * @param session 新建立的 WebSocket 会话
     * @throws Exception 异常信息
     */
    @Override
    public void afterConnectionEstablished(WebSocketSession session) throws Exception {
        // 从 attributes 中获取握手时存入的 userId
        String userId = (String) session.getAttributes().get("userId");

        if (userId == null) {
            // 如果 userId 不存在，可以拒绝连接或关闭会话
            log.info("用户未登录，拒绝连接");
            session.close();
            return;
        }

        // 保存 session 到 map 中，key 可以是 userId
        sessions.put(userId, session);
        log.info("用户上线:{}", userId);
        session.sendMessage(new TextMessage("欢迎用户 " + userId + " 进入聊天室！"));
    }


    /**
     * 当 WebSocket 连接关闭时触发。
     * 主要作用：
     * - 从 sessions 映射表中移除已关闭的会话
     * - 记录用户下线日志
     *
     * @param session 被关闭的 WebSocket 会话
     * @param status  会话关闭的状态码和原因
     * @throws Exception 异常信息
     */
    @Override
    public void afterConnectionClosed(WebSocketSession session, CloseStatus status) throws Exception {
        sessions.remove(session.getId());
        log.info("用户下线: {}", session.getId());
    }


    /**
     * 接收到客户端发送的文本消息时触发。
     * 主要作用：
     * - 获取消息内容并打印日志
     * - 将该消息广播给所有当前在线的 WebSocket 客户端
     *
     * @param session 发送消息的客户端会话
     * @param message 文本消息对象
     * @throws Exception 异常信息
     */
    @Override
    protected void handleTextMessage(WebSocketSession session, TextMessage message) throws Exception {
        log.info("收到消息: {}", message.getPayload());
        String payload = message.getPayload();
        if (!JSONUtil.isTypeJSON(payload)) {
            throw new BusinessException(ErrorCode.WEBSOCKET_JSON_ERROR);
        }
        WebSocketMessage webSocketMessage = JSONUtil.toBean(payload, WebSocketMessage.class);
        MessageType msgType = MessageType.fromType(webSocketMessage.getType());
        switch (msgType) {
            case PRIVATE:
                // 私聊逻辑
                break;
            case GROUP:
                // 群聊逻辑
                for (WebSocketSession webSocketSession : sessions.values()) {
                    webSocketSession.sendMessage(new TextMessage("用户 " + webSocketMessage.getFrom() + " 给你发来消息：" + webSocketMessage.getContent()));
                }
                break;
            case BROADCAST:
                // 广播逻辑
                break;
            case NOTICE:
                // 通知逻辑
                break;
            default:
                throw new BusinessException(ErrorCode.WEBSOCKET_TYPE_ERROR);
        }
    }
}
